"""
@file: models.py
@author: lingdubing
@desc: 数据库模型文件
@character: utf-8
"""

from datetime import datetime

from sqlalchemy.orm import DeclarativeBase, declared_attr
from sqlalchemy.ext.asyncio import AsyncAttrs
from sqlalchemy.orm import relationship, Mapped, mapped_column
from sqlalchemy import Integer, String, Boolean, DateTime, func, inspect, ForeignKey, JSON, Column



# 使用命令：alembic init alembic 初始化迁移数据库环境
# 这时会生成alembic文件夹 和 alembic.ini文件
class BasicModel(AsyncAttrs, DeclarativeBase):
    """
    公共 ORM 模型，基表
    """
    __abstract__ = True
    create_by: Mapped[str] = mapped_column(String(255), comment="创建者")
    update_by: Mapped[str] = mapped_column(String(255), comment="更新者")

    create_time: Mapped[datetime] = mapped_column(DateTime, default=func.now(), server_default=func.now(), comment='创建时间')
    update_time: Mapped[datetime] = mapped_column(
        DateTime,
        default = func.now(),
        server_default=func.now(),
        onupdate=func.now(),
        comment='更新时间'
    )
    # delete_datetime: Mapped[datetime | None] = mapped_column(DateTime, nullable=True, comment='删除时间')
    # is_delete: Mapped[bool] = mapped_column(Boolean, default=False, comment="是否软删除")

    @classmethod
    def get_column_attrs(cls) -> list:
        """
        获取模型中除 relationships 外的所有字段名称
        :return:
        """
        mapper = inspect(cls)

        return mapper.column_attrs.keys()

    @classmethod
    def get_attrs(cls) -> list:
        """
        获取模型所有字段名称
        :return:
        """
        mapper = inspect(cls)
        return mapper.attrs.keys()

    @classmethod
    def get_relationships_attrs(cls) -> list:
        """
        获取模型中 relationships 所有字段名称
        :return:
        """
        mapper = inspect(cls)
        return mapper.relationships.keys()






class UserRoleLink(BasicModel):
    __tablename__ = "userrolelink"
    user_id: Mapped[str] = mapped_column(
        String(255),
        ForeignKey("user.user_id", ondelete='CASCADE'),
        primary_key=True,
        unique=True,
        comment="用户ID"
    )
    role_id: Mapped[str] = mapped_column(
        String(255),
        ForeignKey("role.role_id", ondelete='CASCADE'),
        primary_key=True,
        comment="角色ID"
    )
    user: Mapped["User"] = relationship(foreign_keys=user_id, back_populates="user_role_links")
    role: Mapped["Role"] = relationship(foreign_keys=role_id, back_populates="user_links")


class RoleAccessLink(BasicModel):
    __tablename__ = "roleaccesslink"
    role_id: Mapped[str] = mapped_column(
        String(255),
        ForeignKey("role.role_id", ondelete='CASCADE'),
        primary_key=True,
        comment="角色ID"
    )
    access_id: Mapped[str] = mapped_column(
        String(255),
        ForeignKey("access.access_id", ondelete='CASCADE'),
        primary_key=True,
        comment="权限ID"
    )

    role: Mapped["Role"] = relationship(foreign_keys=role_id, back_populates="access_links")
    access: Mapped["Access"] = relationship(foreign_keys=access_id, back_populates="access_role_links")


class User(BasicModel):
    __tablename__ = "user"
    id:  Mapped[int] = mapped_column(Integer, autoincrement=True, primary_key=True, comment='主键ID')
    user_id: Mapped[str] = mapped_column(String(255), index=True, comment='用户ID,用户的唯一标识')
    username: Mapped[str] = mapped_column(String(255), index=True, comment="用户名")
    password: Mapped[str] = mapped_column(String(255), comment="密码")
    user_status: Mapped[int] = mapped_column(Integer, default=1, index=True, comment="用户状态,0为禁用状态,1为可用状态,2表示正在骑行状态")

    # 附加的属性
    user_role_links: Mapped[list["UserRoleLink"]] = relationship(back_populates="user")
    records: Mapped[list["Record"]] = relationship(back_populates="user")


class Role(BasicModel):
    __tablename__ = "role"
    id: Mapped[int] = mapped_column(Integer, autoincrement=True, primary_key=True, comment='主键ID')
    role_id: Mapped[str] = mapped_column(String(255), index=True, comment='角色ID,角色的唯一标识')
    role_name: Mapped[str] = mapped_column(String(255), comment="角色名")
    role_desc: Mapped[str | None] = mapped_column(String(255), nullable=True, default=None, comment="角色描述")

    user_links: Mapped[list["UserRoleLink"]] = relationship(back_populates="role")
    access_links: Mapped[list["RoleAccessLink"]] = relationship(back_populates="role")


class Access(BasicModel):
    __tablename__ = "access"
    id: Mapped[int] = mapped_column(Integer, autoincrement=True, primary_key=True, comment='主键ID')
    access_id: Mapped[str] = mapped_column(String(255), index=True, comment='权限ID,权限的唯一标识')
    access_name: Mapped[str] = mapped_column(String(255), comment="权限名")
    access_desc: Mapped[str | None] = mapped_column(String(255), nullable=True, default=None, comment="权限描述")
    access_url: Mapped[str | None] = mapped_column(String(255), nullable=True, default=None, comment="权限URL")
    parent_id: Mapped[str | None] = mapped_column(String(255), nullable=True, default=None, comment="父ID")
    is_menu: Mapped[bool] = mapped_column(Boolean, default=False, comment="是否为菜单")
    is_verify: Mapped[bool] = mapped_column(Boolean, default=True, comment="是否需要验证")

    access_role_links: Mapped[list[RoleAccessLink]] = relationship(back_populates="access")


class Machine(BasicModel):
    __tablename__ = "machine"
    id: Mapped[int] = mapped_column(Integer, autoincrement=True, primary_key=True, comment='主键ID')
    machine_id: Mapped[str] = mapped_column(String(255), index=True, comment='电动车ID,电动车的唯一标识')
    machine_point: Mapped[dict | None] = mapped_column(JSON, nullable=True, default=None, comment="电动车位置")
    machine_battery: Mapped[int] = mapped_column(Integer, default=100, comment='电动车电量')
    status: Mapped[int] = mapped_column(Integer, default=1, comment='电动车状态,0为正在骑行中,1为空闲状态,2为损坏,3为正在停止')
    machine_photo: Mapped[str | None] = mapped_column(String(255), nullable=True, default=None, comment="电动车照片")

    # area_id: str = Field(foreign_key="area.area_id", description="区域ID")
    area_id: Mapped[str] = mapped_column(
        String(255),
        ForeignKey("area.area_id", ondelete='CASCADE'),
        comment="区域ID"
    )
    area: Mapped["Area"] = relationship(foreign_keys=area_id, back_populates="machines")
    records: Mapped[list["Record"]] = relationship(back_populates="machine")



class Area(BasicModel):
    __tablename__ = "area"
    id: Mapped[int] = mapped_column(Integer, autoincrement=True, primary_key=True, comment='主键ID')
    area_id: Mapped[str] = mapped_column(String(255), index=True, comment="区域ID,区域的唯一标识")
    area_name: Mapped[str | None] = mapped_column(String(255), nullable=True, default=None, comment="区域名")
    area_desc: Mapped[str | None] = mapped_column(String(255), nullable=True, default=None, comment="区域描述")

    machines: Mapped[list[Machine]] = relationship(back_populates="area")



class Record(BasicModel):
    __tablename__ = "record"
    id: Mapped[int] = mapped_column(Integer, autoincrement=True, primary_key=True, comment='主键ID')
    record_id: Mapped[str] = mapped_column(String(255), index=True, comment="记录ID,记录的唯一标识")
    start_time: Mapped[datetime | None] = mapped_column(DateTime, default=None, nullable=True,  comment='开始时间')
    end_time: Mapped[datetime | None] = mapped_column(DateTime, server_default=func.now(), nullable=True, comment='结束时间')
    stop_time: Mapped[int] = mapped_column(Integer, default=0, comment="停车时间")
    consume_battery: Mapped[int] = mapped_column(Integer, default=0, comment="消耗电量")
    tracejectory: Mapped[dict | None] = mapped_column(JSON, nullable=True, default=None, comment="轨迹")

    # 附加属性
    user_id: Mapped[str] = mapped_column(
        String(255),
        ForeignKey("user.user_id", ondelete='CASCADE'),
        comment="用户ID"
    )
    user: Mapped[User] = relationship(foreign_keys=user_id, back_populates="records")
    machine_id: Mapped[str] = mapped_column(
        String(255),
        ForeignKey("machine.machine_id", ondelete='CASCADE'),
        comment="电动车ID"
    )
    machine: Mapped[Machine] = relationship(foreign_keys=machine_id, back_populates="records")



